package erfgame.core.world.terrain.color;

import java.awt.image.BufferedImage;
import java.util.Random;


import erfgame.core.util.ColorUtils;
import erfgame.core.world.terrain.TerrainColorSource;

public final class MappedTerrainColorSource implements TerrainColorSource {
	
	public static final int[][][] getRandomColorMap( int minColor, int maxColor, Random random, int width, int height, int depth ) {
		int[][][] colorMap = new int[ width ][ height ][ depth ];
		// TODO : reverse loops
		for( int x = 0; x<width; x++ ) {
			for( int y = 0; y<height; y++ ) {
				SampledTerrainColorSource.getRandomColors( minColor, maxColor, random, colorMap[x][y] );
			}
		}
		return colorMap;
	}
	
	public static final int[][][] getStaticColorMap( int color, int width, int height, int depth ) {
		int[][][] colorMap = new int[ width ][ height ][ depth ];
		// TODO : reverse loops
		for( int x = 0; x<width; x++ ) {
			for( int y = 0; y<height; y++ ) {
				for( int z = 0; z<depth; z++ ) {
					colorMap[x][y][z] = color;
				}
			}
		}
		return colorMap;		
	}
	
	public static final int[][][] carveBricks( int gapColor, int width, int height, int depth, int[][][] colorMap ) {
		for( int x=0; x<width; x++ ) {
			for( int y=0; y<height; y++ ) {
				for( int z=0; z<depth; z++ ) {
					if( x == y || (width-x) == y || z == depth-1 ) {
						// TODO : average based on distance
						colorMap[x][y][z] = gapColor;
					}
				}
			}
		}
		return colorMap;
	}
	
	public static final int[][][] overlayXY( BufferedImage image, int width, int height, int minz, int maxz, int[][][] colorMap ) {
		int imageWidth = image.getWidth();
		int imageHeight = image.getHeight();
		for( int x=0; x<width; x++ ) {
			for( int y=0; y<height; y++ ) {
				int overlapColor = image.getRGB( x % imageWidth, y % imageHeight );
				int overlapAlpha = (overlapColor>>24) & 0xFF; 
				int invertedAlpha = 255 - overlapAlpha;
				for( int z=minz; z<maxz; z++ ) {
					int existingColor = colorMap[x][y][z];
					// merge in
					int newColor = ColorUtils.averageColors(overlapColor, overlapAlpha, existingColor, invertedAlpha);
					colorMap[x][y][z] = newColor;
				}
			}
		}
		return colorMap;
	}
	
	public static final int[][][] overlayXZ( BufferedImage image, int width, int miny, int maxy, int depth, int[][][] colorMap ) {
		int imageWidth = image.getWidth();
		int imageHeight = image.getHeight();
		for( int x=0; x<width; x++ ) {
			for( int z=0; z<depth; z++ ) {
				int overlapColor = image.getRGB( x % imageWidth, z % imageHeight );
				int overlapAlpha = (overlapColor>>24) & 0xFF; 
				int invertedAlpha = 255 - overlapAlpha;
				for( int y=miny; y<maxy; y++ ) {
					int existingColor = colorMap[x][y][z];
					// merge in
					int newColor = ColorUtils.averageColors(overlapColor, overlapAlpha, existingColor, invertedAlpha);
					colorMap[x][y][z] = newColor;
				}				
			}
		}		
		return colorMap;
	}
	
	private int[][][] maxColorMap;
	private int[][][] minColorMap;
	private int[][][] colorMap;
	private int width;
	private int height;
	private int depth;
	
	public MappedTerrainColorSource( int[][][] minColorMap, int[][][] maxColorMap, int[][][] colorMap, int width, int height, int depth ) {
		this.colorMap = colorMap;
		this.maxColorMap = maxColorMap;
		this.minColorMap = minColorMap;
		this.width = width;
		this.height = height;
		this.depth = depth;
	}

	public int getColor(int x, int y, int z, int mult, int div, int dCeiling) {
		int mx = x % this.width;
		int my = y % this.height;
		int mz = z % this.depth;
		int middle = this.colorMap[mx][my][mz];
		int color;
		if( mult > 0 ) {
			int extreme = this.maxColorMap[mx][my][mz];
			color = ColorUtils.multiplyColor(middle, extreme, mult, div );
		} else {
			int extreme = this.minColorMap[mx][my][mz];
			color = ColorUtils.multiplyColor(middle, extreme, -mult, div );
		}
		return color;
	}

}